#ifndef _MJ_H_
#define _MJ_H_

#include <string>
#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <algorithm>
#include <tuple>

using namespace std;

//麻将子的定义
enum mjcode
{
	W1 = 11, W2, W3, W4, W5, W6, W7, W8, W9, // 1~9 万
	S1 = 31, S2, S3, S4, S5, S6, S7, S8, S9, // 1~9 条(索)
	T1 = 51, T2, T3, T4, T5, T6, T7, T8, T9, // 1~9 筒(饼)
	Zh = 71, Fa = 81, Ba = 91              // 中, 发, 白
};

//一张麻将牌的抽象 
class Mj
{
public:
	//获取牌组中各颜色数量 W S T
	static tuple<int, int, int> GetColorNum(const vector<Mj>& mjs)
	{
		int color[3] = { 0 };
		for (const auto &mj : mjs)
		{
			switch (mj.val/10)
			{
			case 1:color[0]++; break;
			case 3:color[1]++; break;
			case 5:color[2]++; break;
			default:
				break;
			}
		}
		return make_tuple(color[0], color[1], color[2]);
	}
	Mj(int _mj_val = 0)
	{
		val = _mj_val;
	}

	//牌的花色
	int color();
	int word()
	{
		return val % 10;
	}

	//翻牌鸡牌
	Mj next_fangpai_mj();

	//比较两张麻将
	static int comparemj(Mj m1, Mj m2);
	//比较两张麻将
	bool operator==(const Mj& mj) const
	{
		return mj.val == this->val;
	}

	bool operator!=(const Mj& mj) const
	{
		return !(*this == mj);
	}
	bool operator == (int mj_val) const
	{
		return this->val == mj_val;
	}
	//比较两张麻将
	bool operator < (const Mj& mj) const
	{
		return this->val < mj.val;
	}
	bool operator > (const Mj& mj) const
	{
		return this->val > mj.val;
	}
	//左移几张牌
	Mj operator - (int num);
	//右移几张牌
	Mj operator + (int num);
	//获取麻将打印字串
	std::string get_mj();
	//升序排列
	static void sort_by_ascending(std::vector<Mj> &v)
	{
		sort(v.begin(), v.end(), [](const Mj &a, const Mj &b)
		{
			if (a.val < b.val)
				return true;
			else
				return false;
		});
	}
	//打印一堆麻将
	static void dump_mjs(std::vector<Mj> &v, string str = "mjs")
	{
		fprintf(stdout, "[%s]: [[ ", str.c_str());
		for (std::vector<Mj>::iterator it = v.begin(); it != v.end(); it++)
		{
			fprintf(stdout, "%s ", it->get_mj().c_str());
		}
		fprintf(stdout, "]]\n");
	}
	//检查麻将牌是否合法
	bool check_mjval()
	{
		return ((val >= S1 && val <= S9) ||
			(val >= W1 && val <= T9) ||
			(val >= W1 && val <= W9));
	}
	//检查麻将牌是否合法
	bool static check_mjval(int val)
	{
		return ((val >= S1 && val <= S9) ||
			(val >= W1 && val <= T9) ||
			(val >= W1 && val <= W9));
	}

public:
	int val;

};

#endif
